package org.oslims.client.presenter;

import java.util.List;
import java.util.Set;

import org.oslims.client.AsyncCall;
import org.oslims.client.MainEventBus;
import org.oslims.client.service.UserServiceAsync;
import org.oslims.client.uicomponents.SortableHeader;
import org.oslims.client.uicomponents.editbox.EditLabManagerBox;
import org.oslims.client.view.LabManagerEditorView;
import org.oslims.client.view.impl.LabManagerEditorViewImpl;
import org.oslims.domain.LabManager;

import com.google.gwt.cell.client.ButtonCell;
import com.google.gwt.cell.client.CheckboxCell;
import com.google.gwt.cell.client.FieldUpdater;
import com.google.gwt.cell.client.ValueUpdater;
import com.google.gwt.core.client.GWT;
import com.google.gwt.event.dom.client.ClickEvent;
import com.google.gwt.event.dom.client.ClickHandler;
import com.google.gwt.event.logical.shared.SelectionEvent;
import com.google.gwt.event.logical.shared.SelectionHandler;
import com.google.gwt.user.cellview.client.Column;
import com.google.gwt.user.cellview.client.TextColumn;
import com.google.gwt.user.client.ui.TabPanel;
import com.google.gwt.validation.client.InvalidConstraint;
import com.google.gwt.validation.client.interfaces.IValidator;
import com.google.gwt.view.client.ListView;
import com.google.gwt.view.client.Range;
import com.google.gwt.view.client.ListView.Delegate;
import com.mvp4g.client.annotation.InjectService;
import com.mvp4g.client.annotation.Presenter;
import com.mvp4g.client.presenter.BasePresenter;

@Presenter(view = LabManagerEditorViewImpl.class)
public class LabManagerPresenter extends BasePresenter<LabManagerEditorView, MainEventBus> {

	private UserServiceAsync userService;
	private IValidator<LabManager> labManagerValidator;

	private String currentSortProperty = "firstName";
	private Boolean currentSortDesc = false;

	public LabManagerPresenter() {
		labManagerValidator = GWT.create(LabManager.class);
	}

	public void onInizializeLabManagerManagement(TabPanel tp) {
		tp.add(view.getViewWidget(), "Lab Manager");

		tp.addSelectionHandler(new SelectionHandler<Integer>() {

			@Override
			public void onSelection(SelectionEvent<Integer> event) {
				if (event.getSelectedItem() == 1) {
					refreshData();
				}

			}
		});
	}

	@Override
	public void bind() {
		// refreshLabManagers();

		bindEditBox();

		addColumns();

		setDelegate();

	}

	private void refreshData() {
		userService.getLabManagerCount(new AsyncCall<Integer>() {

			@Override
			protected void onFailureE(Throwable caught) {
				eventBus.error(caught.getMessage());
			}

			@Override
			protected void onSuccessE(Integer result) {
				view.getTable().setDataSize(result, true);

				if (result < view.getDefaultPageSize()) {
					view.getPager().setVisible(false);
					view.getTable().setPageSize(result);
				}
				view.getTable().refresh();
			}
		});
	}

	private void setDelegate() {
		view.getTable().setDelegate(new Delegate<LabManager>() {

			@Override
			public void onRangeChanged(ListView<LabManager> listView) {

				final Range r = listView.getRange();

				userService.getAllLabManager(r.getStart(), r.getLength(), currentSortProperty, currentSortDesc, new AsyncCall<List<LabManager>>() {

					@Override
					protected void onFailureE(Throwable caught) {
						eventBus.error(caught.getMessage());
					}

					@Override
					protected void onSuccessE(List<LabManager> result) {
						view.getTable().setData(r.getStart(), r.getLength(), result);
						view.getTable().redraw();
					}
				});
			}
		});
	}

	private void addColumns() {
		final SortableHeader nameHeader = new SortableHeader("First Name", "firstName");
		nameHeader.setSorted(true);

		nameHeader.setUpdater(new ValueUpdater<String>() {

			@Override
			public void update(String value) {
				nameHeader.toggleReverseSort();
				currentSortProperty = nameHeader.getPropertyName();
				currentSortDesc = nameHeader.getReverseSort();
				view.getTable().refresh();
				view.getTable().refreshHeaders();
			}
		});

		view.getTable().addColumn(new TextColumn<LabManager>() {

			@Override
			public String getValue(LabManager object) {
				return object.getFirstName();
			}
		}, nameHeader);

		view.getTable().addColumn(new TextColumn<LabManager>() {

			@Override
			public String getValue(LabManager object) {
				return object.getLastName();
			}
		}, "Last Name");

		view.getTable().addColumn(new TextColumn<LabManager>() {

			@Override
			public String getValue(LabManager object) {
				return object.getEMail();
			}
		}, "EMail");

		view.getTable().addColumn(new Column<LabManager, Boolean>(new CheckboxCell()) {

			@Override
			public Boolean getValue(LabManager object) {
				return object.getActive();
			}
		}, "Active");

		Column<LabManager, String> editColumn = new Column<LabManager, String>(new ButtonCell()) {

			@Override
			public String getValue(LabManager object) {
				return "Edit";
			}
		};

		editColumn.setFieldUpdater(new FieldUpdater<LabManager, String>() {

			@Override
			public void update(int index, LabManager object, String value) {
				view.getEditLabManagerBox().showEdit(object);
			}
		});

		view.getTable().addColumn(editColumn);
	}

	private void bindEditBox() {
		view.getAddLabManagerButton().addClickHandler(new ClickHandler() {

			@Override
			public void onClick(ClickEvent arg0) {
				view.getEditLabManagerBox().showNew();
			}
		});

		view.getEditLabManagerBox().getCancelButton().addClickHandler(new ClickHandler() {

			@Override
			public void onClick(ClickEvent arg0) {
				view.getEditLabManagerBox().hide();
			}
		});

		view.getEditLabManagerBox().getSaveButton().addClickHandler(new ClickHandler() {

			@Override
			public void onClick(ClickEvent arg0) {
				if (view.confirmEdit("Do you want to save your changes?"))
					saveLabManager();
			}

		});
	}

	@InjectService
	public void setUserService(UserServiceAsync userService) {
		this.userService = userService;
	}

	public void saveLabManager() {

		EditLabManagerBox editBox = view.getEditLabManagerBox();
		LabManager tempLabManager = editBox.getLabManager();

		if (tempLabManager == null)
			tempLabManager = new LabManager();

		tempLabManager.setActive(editBox.getActive().getValue());
		tempLabManager.setEMail(editBox.getEMail().getValue());
		tempLabManager.setFirstName(editBox.getFirstName().getValue());
		tempLabManager.setLastName(editBox.getLastName().getValue());
		tempLabManager.setPassword(editBox.getPassword().getValue());

		Set<InvalidConstraint<LabManager>> labManagerErrors = labManagerValidator.validate(tempLabManager);

		if (labManagerErrors.size() > 0) {
			for (InvalidConstraint<LabManager> ic : labManagerErrors) {
				editBox.showError(ic.getItemName(), ic.getMessage());
			}
			return;
		}

		userService.saveOrUpdateLabManager(tempLabManager, new AsyncCall<Void>() {

			@Override
			public void onSuccessE(Void result) {

				view.getEditLabManagerBox().hide();
				refreshData();
			}

			@Override
			public void onFailureE(Throwable error) {
				eventBus.error(error.getMessage());
			}
		});
	}
}
